/*!
 * \file set_relation_dot_visitor.h
 *
 * \brief Declarations of the set_relation_dot_visitor that traverses the Set
 *        and Relation structures.
 *
 * \date Started: 7/6/2010
 * \date Last Modified: 7/6/2010
 * \authors Alan LaMielle
 * \authors Nicholas Jeanette
 *
 * Copyright (c) 2010, Colorado State University <br>
 * All rights reserved. <br>
 * See ../../COPYING for details. <br>
 */

#ifndef SET_RELATION_DOT_VISITOR_H_
#define SET_RELATION_DOT_VISITOR_H_

#include <iegenlib/iegenlib.h>

#include <fstream>
#include <sstream>
#include <sstream>
using std::stringstream;

namespace iegenlib{

/*!
 * \class SetRelationDotVisitor
 * \brief The dot visitor of the Set and Relation classes
 *
 * This visitor will traverse the structure created by the Set and Relation
 * classes and create a string that is a formatted dot file that will represent
 * the entire structure.
 */
class SetRelationDotVisitor: public SRVisitor{
public:

   /*!
   * Used for popping the stack of counts, when the stack is empty appends final
   * }
   * @param node node to do tasks on
   */
   void defaultOut();

   /*!
   * Used for general tasks to be done going in every visited node
   * @param node node to do tasks on
   */
   void defaultIn();

   /*!
   * Used to connect the nodes together, uses a stack and increments a counter
   */
   void connectSegs(int,int);

   /*!
   * Used for set this is where the set mSt and mConSet node get added
   * @param node node to do tasks on
   */
   void SetIn(const Set* );

   /*!
   * Used to pop off the stack when leaving the set node
   * @param set node to do tasks on
   */
   void SetOut(const Set*);

   /*!
   * Used for set this is where the set mSt and mConSet and Arity node get added
   * @param relation to do tasks on
   */
   void RelationIn(const Relation*);

   /*!
   * Used to pop off the stack when leaving the relation node
   * @param relation to do tasks on
   */
   void RelationOut(const Relation* x);

   /*!
   * Used to build the section of the dot file that lists all items in the
   * symbol table as well as the info on each of the elements in the table, id
   * type and column
   * @param symbol table to do tasks on
   */
   void SymbolTableIn(SymbolTable* x);

   /*!
   * Used to pop off the stack when leaving the symbol table, needed as we
   * pushed an extra time
   * @param set node to do tasks on
   */
   void SymbolTableOut(SymbolTable* x);

   /*!
   * Used to add the conjunction box to the dot file
   * @param set node to do tasks on
   */
   void SRConjunctionIn(const SRConjunction* x);

   /*!
   * SRConjunction out rebuilds all the tuple information so it can be added to
   * the mTuple field of the conjunction box
   * @param set node to do tasks on
   */
   void SRConjunctionOut(const SRConjunction* x);

   /*!
   * iterates through the equality node in order to build the expvec and link
   * all the values in the symbol table to that expVec. ExpVec is built to have
   * all positive coeffs, the actual coeffs of the expvec are next to the
   * symtable entries.
   * @param set node to do tasks on
   */
   void SREqualityIn(const SREquality* x);

   /*!
   * iterates through the equality node in order to build the expvec and link
   * all the values in the symbol table to that expVec. ExpVec is built to have
   * all positive coeffs, the actual coeffs of the expvec are next to the
   * symtable entries.
   * @param set node to do tasks on
   */
   void SRInequalityIn(const SRInequality* x);

   inline void ExpVecOut(const ExpVec* x){};

   /*!
   * creates the actual box for tuple vars, has the id and column info
   * @param set node to do tasks on
   */
   void TupleVarIn(TupleVar* x);

   /*!
   * creates the actual box for tuple vars, has the id and column info
   * @param set node to do tasks on
   */
   void ExistVarIn(ExistVar* x);

   /*!
   * creates the actual box for tuple vars, has the id and column info
   * @param set node to do tasks on
   */
   void SymConstIn(SymConst* x);

   /*!
   * creates the actual box for tuple vars, has the id and column info
   * @param set node to do tasks on
   */
   void UFCallIn(UFCall* x);

   inline void TupleTypeOut(const TupleType* node){};
  /*
   * returns the all information needed to make a dot file as a string. This can
   * then be passed in a file to actually create a dot file.
   * @return a string representation of the dot file
   */
   inline std::string returnString(){return filestr.str();};

   /*
   * A function that formats the output for the expression vector in the
   * conjunction sections. The format is placing all positive coeffs on one side
   * and all negative coeffs on the other.
   * @param boolean of if the format should be for the equality or inequality
   * equality = true inequality = false
   * @param expvec the expression vector for the conjunction
   */
   void formatPrint(bool x, ExpVec y);

private:

   ///counter used for connecting nodes together
   int count;

   ///counter used for arrows out of symbol table entries
   int symcount;

   ///stream we add the output of the dot file to
   std::stringstream filestr;

   ///stack to hold the count, used to connect nodes together
   stack<int> nodeStack;

   /// list of symbol table entries that are tuple var
   list<STE*> tuplist;


   list<TupleType>::const_iterator currConjBegin;
   list<TupleType>::const_iterator currConjEnd;

   void coefficientHelper(bool* found, int* count, string* out, ExpVec* expr, STE* symbol, stringstream* constraint, stringstream* negConstraint, bool first);
   void sideNodeHelper(string* out, int nodeloc);

   SymbolTable* ST;
};

}//end namespace iegenlib

#endif /* SET_RELATION_DOT_VISITOR_H_ */
